#include "FillAction.hpp"

FillAction::FillAction(Map* map, sf::Rect<int> marquee, int x, int y, int setTile, int setLayer, char* name){
    desc = "Used Fill on layer " + StringHelper::itos(setLayer) + " with " + name;
    marqueeSelection = marquee;
    targetX = x;
    targetY = y;
    target = map;
    layer = setLayer;
    value = setTile;
    resizeResult = 0;
    perform();
}

void FillAction::perform(){
    tiles.clear();
    resizeResult = 0;
    needsResize = MapResizer::needsResize(target, &marqueeSelection);
    if(!needsResize){
        startTile = targetY*target->width + targetX;
        originalValue = target->tiles[startTile][layer];
    }else{
        resizeResult = MapResizer::resizeByMarquee(target, &marqueeSelection);
        if(resizeResult == 0){
            performed = false;
            return;
        }
        startTile = (resizeResult->shiftY + targetY)*target->width + (targetX + resizeResult->shiftX);
        marqueeSelection.left += resizeResult->shiftX;
        marqueeSelection.top += resizeResult->shiftY;
        originalValue = NO_SPRITE;
    }
    fill(startTile);
    performed = true;
}

/** 
* Recursive tile setting of all matching tiles.
*/
void FillAction::fill(int tile){
    if(marqueeSelection.width != 0 && marqueeSelection.height != 0){
        if(!(tile%target->width >= marqueeSelection.left && tile%target->width < (marqueeSelection.left + marqueeSelection.width)
            && tile/target->width >= marqueeSelection.top && tile/target->width < (marqueeSelection.top + marqueeSelection.height)))
            return;
    }

    if(target->tiles[tile][layer] == originalValue){
        tiles.push_back(tile);
        target->tiles[tile][layer] = value;
    }else{
        return;
    }

    if(tile%target->width > 0){
        fill(tile-1);
    }
    if(tile%(target->width-1) != 0){
        fill(tile+1);
    }
    if(tile > target->width){
        fill(tile-target->width);
    }
    if(tile < target->width*target->height - target->width - 1){
        fill(tile+target->width);
    }
}

void FillAction::undo(){
    for(int i = 0; i < tiles.size(); i++){
            target->tiles[tiles.at(i)][layer] = originalValue;
    }
    if(resizeResult != 0){
        MapResizer::shrink(target, resizeResult);
    }
}

FillAction::~FillAction(){
    target = 0;
}